#include "../header.h"

//TODO 服务端编程
//1.socket 建立服务端套接字   - sid建立链接
//2.bind - port - ip - 网卡
//3.listen - 监听。
//4.accept - 链接-的结果  cid - 读写套接字
//5.读写
//6.关闭

//2个字符串进去。
int TCP_Init(const char * port,const char *ip)
{
    //1.
    int sid = socket(AF_INET,SOCK_STREAM,0);
    if(sid < 0 )
    {
        perror("socket error\n");
        return -1;
    }
    printf("套接字建立成功:%d\n",sid);
    //实际地址结构体，
    struct sockaddr_in saddr = {0};
    //ipv4协议族
    saddr.sin_family = AF_INET;
    //ip + port填写。
    saddr.sin_addr.s_addr = inet_addr(ip);
    saddr.sin_port = htons(atoi(port));  
    //port + sid + ip
    //2通用地址结构体
   if(bind(sid,(struct sockaddr*)&saddr,sizeof(saddr)) < 0 )
    {
        perror("bind error\n");
    }
    printf("绑定成功!\n");
    //3
    if(listen(sid,10) < 0 )
    {
        perror("监听失败!\n");
    }
    printf("监听成功!\n");
    //4 链接 - 阻塞  
    //第二个参数是对面的地址结构体。
    struct sockaddr_in caddr = {0};
    int size = sizeof(caddr);
    int cid =  -1 ;
    
    //单用户 - 一次读写。
    //读写操作 - 先读再写
    char bufs[128] = "";
    int readlen = 0 ;
    char bufn[128] = "";
    //先读-再写。
    //主要任务 - 键盘-屏幕-文件-客户端cid -sid
     char ipk[16] = {0};
    while(1)
    {   
        //阻塞
        cid = accept(sid, (struct sockaddr *)&caddr, &size);
        if (cid < 0)
        {
            perror("链接失败!\n");
        }
        // 本cid用来进行读写。
        printf("链接成功 客户端已经登录 :cid = %d\n", cid);
        // 解析客户端数据 - 解析客户端 ip + port
        printf("客户端的端口号:%d\n", ntohs(caddr.sin_port));
        printf("客户端的ip地址是:%s\n", inet_ntop(AF_INET, &caddr.sin_addr, ipk, sizeof(ipk)));
        // char bufk[128];
        // sprintf(bufk,"%d",1000);
        // strcat(ipk,buk)
        //保存聊天记录。open - write - close 
        //对面的ip：port:内容
        bzero(bufs,sizeof(bufs));
        while(strncmp(bufs,"quit",4))
        {
            //清空缓冲区bufs
            bzero(bufs,sizeof(bufs));
            //read阻塞
            readlen = recv(cid,bufs,sizeof(bufs),0);
            printf("客户端发送过来的数据是:%s 数据长度是:%d\n",bufs,readlen);

            //写数据
            bzero(bufn,sizeof(bufn));
            printf("请输入数据:");
            //从键盘接收的数据 - 发送到对面。
            fgets(bufn,sizeof(bufn)-1,stdin);
            //发送数据
            send(cid,bufn,strlen(bufn),0);
        }
        //close(cid);
        //两边的读写都关掉。
        shutdown(cid,SHUT_RDWR);
       // shutdown(sid,SHUT_RDWR);
    }
    return 0;

}
/**
 * @函数原型: ssize_t recv(int sockfd, void *buf, size_t len, int flags);
 * @函数功能: 从套接字中读数据过来。
 * @参数说明: 
 * @       参数1: sockfd  客户端套接字
 * @       参数2: buf ： 读出来的数据存放的位置。
 * @       参数3: len: 长度。
 * flags ： 0。
 * @返回值: 实际读到的字节数。
 * @param {int} argc
 */
/**
 * @函数原型: ssize_t send(int sockfd, const void *buf, size_t len, int flags);
 * @函数功能: 发送数据到 cid上。
 * @参数说明: 
 * @       参数1: buf ： 要发送的数据
 * @       参数2: len ： 要发送的长度
 * @       参数3: flags ： 0。
 * @返回值: 实际发送的字节个数。
 * @param {int} argc
 */
int main(int argc, char const *argv[])
{
    //参数判断
    if(argc < 3)
    {
        perror("usage:./a.out + ip + port\n");
        return -1;
    }
    //端口字符串argv[2],ip字符串arg[1];
    //每个函数的返回值可以判定本函数是否执行成功。
    TCP_Init(argv[2],argv[1]);


    return 0;
}
